package com.eystar.ext.plugin.crate.db;

import java.util.ArrayList;
import java.util.List;

import com.eystar.ext.kit.UUIDKit;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log4jLog;
import com.jfinal.plugin.activerecord.ActiveRecordException;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;

/**
 * 使用CrateDB 方法。<br>
 * 1、CrateDb.init(驱动,集群地址,是否显示sql); 或者 直接使用 CrateDb.init(集群地址) 默认显示sql<Br>
 * 2、CrateDb.find(sql);
 * @author zhangjian
 *
 */
public class CrateDb {
	
	public static final Log4jLog logger = Log4jLog.getLog(CrateDb.class);
	private static CrateDbPro dbPro = null;
	
	public static String DRIVER;
	public static String URL;
	public static boolean SHOW_SQL;
	
	public static void init(String crateDriver,String crateCluster){
		init(crateDriver, crateCluster,true);
	}
	
	public static void init(String crateDriver,String crateCluster,boolean showSql){
		logger.info("CrateDB init");
		CrateDb.URL = crateCluster;
		CrateDb.DRIVER = crateDriver;
		CrateDb.SHOW_SQL = showSql;
		dbPro = new CrateDbPro();
	}
	
	/**
	 * @see #query(String, String, Object...)
	 */
	public static <T> List<T> query(String sql, Object... paras) {
		return dbPro.query(sql, paras);
	}
	
	/**
	 * @see #query(String, Object...)
	 * @param sql an SQL statement
	 */
	public static <T> List<T> query(String sql) {
		return dbPro.query(sql);
	}
	
	/**
	 * Execute sql query and return the first result. I recommend add "limit 1" in your sql.
	 * @param sql an SQL statement that may contain one or more '?' IN parameter placeholders
	 * @param paras the parameters of sql
	 * @return Object[] if your sql has select more than one column,
	 * 			and it return Object if your sql has select only one column.
	 */
	public static <T> T queryFirst(String sql, Object... paras) {
		return dbPro.queryFirst(sql, paras);
	}
	
	/**
	 * @see #queryFirst(String, Object...)
	 * @param sql an SQL statement
	 */
	public static <T> T queryFirst(String sql) {
		return dbPro.queryFirst(sql);
	}
	
	/**
	 * @see #find(String, String, Object...)
	 */
	public static List<Record> find(String sql, Object... paras) {
		return dbPro.find(sql, paras);
	}
	
	/**
	 * @see #find(String, String, Object...)
	 * @param sql the sql statement
	 */
	public static List<Record> find(String sql) {
		return dbPro.find(sql);
	}
	
	/**
	 * Find first record. I recommend add "limit 1" in your sql.
	 * @param sql an SQL statement that may contain one or more '?' IN parameter placeholders
	 * @param paras the parameters of sql
	 * @return the Record object
	 */
	public static Record findFirst(String sql, Object... paras) {
		return dbPro.findFirst(sql, paras);
	}
	/**
	 * @see #findFirst(String, Object...)
	 * @param sql an SQL statement
	 */
	public static Record findById(String tablename, String id) {
		String sql = "select * from "+tablename+" where id=?";
		return dbPro.findFirst(sql,id);
	}
	/**
	 * @see #findFirst(String, Object...)
	 * @param sql an SQL statement
	 */
	public static Record findFirst(String sql) {
		return dbPro.findFirst(sql);
	}
	public static boolean save(String tableName, Record record) {
		if(StrKit.isBlank(record.getStr("id"))){
			record.set("id", UUIDKit.nextShortUUID());
		}
		StringBuilder sql = new StringBuilder();
		List<Object> paras = new ArrayList<Object>();
		dbPro.forDbSave(tableName, record, sql, paras);
		return dbPro.update(sql.toString(), paras.toArray())>0;
	}
	public static void batch(List<String> sqlList, int batchSize) {
		if(sqlList == null || sqlList.isEmpty()) return ;
		dbPro.batch(sqlList, batchSize);
	}
	public static void batchSave(String tableName, List<Record> recordlist, int batchSize) {
		if(recordlist == null || recordlist.isEmpty()) return ;
		dbPro.batchSave(tableName, recordlist, batchSize);
	}
	public static void batchSavePassError(String tableName, List<Record> recordlist, int batchSize) {
		if(recordlist == null || recordlist.isEmpty()) return ;
		dbPro.batchSavePassError(tableName, recordlist, batchSize);
	}
	/**
	 * Update record with default primary key.
	 * <pre>
	 * Example:
	 * Db.update("user", record);
	 * </pre>
	 * @see #update(String, String, Record)
	 */
	public static boolean update(String tableName, Record record) {
		if(StrKit.isBlank(record.getStr("id"))){
			throw new ActiveRecordException("You can't update record without Primary Key, id can not be null.");
		}
		StringBuilder sql = new StringBuilder();
		List<Object> paras = new ArrayList<Object>();
		dbPro.forDbUpdate(tableName, record, sql, paras);
		return dbPro.update(sql.toString(), paras.toArray())>0;
	}
	
	public static void batchUpdate(String tableName, List<Record> recordlist, int batchSize) {
		if(recordlist == null || recordlist.isEmpty()) return ;
		dbPro.batchUpdate(tableName, recordlist, batchSize);
	}
	/**
	 * Execute update, insert or delete sql statement.
	 * @param sql an SQL statement that may contain one or more '?' IN parameter placeholders
	 * @param paras the parameters of sql
	 * @return either the row count for <code>INSERT</code>, <code>UPDATE</code>,
     *         or <code>DELETE</code> statements, or 0 for SQL statements 
     *         that return nothing
	 */
	public static int update(String sql, Object... paras) {
		return dbPro.update(sql, paras);
	}
	
	/**
	 * @see #update(String, Object...)
	 * @param sql an SQL statement
	 */
	public static int update(String sql) {
		return dbPro.update(sql);
	}
	
	/**
	 * @see #paginate(String, int, int, String, String, Object...)
	 */
	public static Page<Record> paginate(int pageNumber, int pageSize, String select, String sqlExceptSelect) {
		return dbPro.paginate(pageNumber, pageSize, select, sqlExceptSelect);
	}
}
